package Vo::ModelVo;

use strict;
use warnings;
use utf8;
use lib './src';

use Utils;
use Vo::ModelPropertyVo;

sub new {
    my ($class, %args) = @_;

    my $self = {
        # 公司名称
        CompanyName => undef,
        # 项目名称
        ProjectName => undef,
        # 聚合根包名
        AggregatePackage => "Domain.AggregatesModel",
        # 数据库映射包名
        TypeConfigurationPackage => "Infrastructure.EntityConfigurations",
        # 强类型 Id
        StronglyId => undef,
        # 强类型 Id 注释
        StronglyIdComment => undef,
        # 是否是聚合根
        IsAggregate => undef,
        # 聚合根名称
        Name => undef,
        # 下滑线名称
        UnderScoreName => undef,
        # 聚合根注释
        Comment => undef,
        # 聚合根属性
        Properties => undef,
        # 基础属性
        BaseProperties => [
            Vo::ModelPropertyVo->new( Type => 'RowVersion', Name => 'RowVersion', Comment => '并发乐观锁', DefaultValue => 'new RowVersion(0)'),
            Vo::ModelPropertyVo->new( Type => 'DateTime', Name => 'CreatedAt', Comment => '创建时间', DefaultValue => 'DateTime.MinValue'),
            Vo::ModelPropertyVo->new( Type => 'string', Name => 'CreatedBy', Comment => '创建者', DefaultValue => 'string.Empty'),
            Vo::ModelPropertyVo->new( Type => 'UpdateTime', Name => 'UpdatedAt', Comment => '更新时间', DefaultValue => 'new UpdateTime(DateTimeOffset.MinValue)'),
            Vo::ModelPropertyVo->new( Type => 'string', Name => 'UpdatedBy', Comment => '更新者', DefaultValue => 'string.Empty'),
            Vo::ModelPropertyVo->new( Type => 'Deleted', Name => 'Deleted', Comment => '是否删除', DefaultValue => 'new Deleted(false)'),
        ],
        # 聚合根关联枚举
        Enums => undef,
        # 模板引擎
        Engine => undef,
        # 聚合根生成内容
        ClassContent => undef,
        # 数据库映射生成内容
        TypeConfigurationContent => undef,
        # 数据表定义语句
        DDLSql => undef,
        # 文件生成目录
        GenerateDir => './public/generate/',
        # 模型配置
        Config => undef,
    };

    foreach my $key (keys %args){
        $self->{$key} = $args{$key};
    }

    # 默认使用 UUID
    if(!defined $self->{Config}->{USE_UUID}){
        $self->{Config}->{USE_UUID} = 1;
    }

    $self->{UnderScoreName} = Camel2UnderScore($self->{Name});

    bless $self, $class;

    return $self;
}

sub setComment {
    my ($self, $comment) = @_;
    $self->{Comment} = $comment;
    $self->{StronglyIdComment} = $comment." Id";
}

sub getComment {
   my ($self) = @_;
   return $self->{Comment};
}

sub setEngine {
    my ($self, $engine) = @_;
    $self->{Engine} = $engine;
}

sub generate {
    my ($self) = @_;
    my $engine = $self->{Engine};
    $engine->process("aggregate.tt2", $self, \$self->{ClassContent})
       || die $engine->error(), "\n";
    $engine->process("typeConfiguration.tt2", $self, \$self->{TypeConfigurationContent})
       || die $engine->error(), "\n";
    $engine->process("ddlSql.tt2", $self, \$self->{DDLSql})
       || die $engine->error(), "\n";
}

sub write{
    my ($self) = @_;
    my $aggregatePackage = $self->{AggregatePackage};
    $aggregatePackage =~ s/\./\//g;
    $aggregatePackage = $self->{GenerateDir}.$aggregatePackage;
    SaveFile($aggregatePackage, $self->{Name}.".cs", $self->{ClassContent});

    my $typeConfigurationPackage = $self->{TypeConfigurationPackage};
    $typeConfigurationPackage =~ s/\./\//g;
    $typeConfigurationPackage = $self->{GenerateDir}.$typeConfigurationPackage;
    SaveFile($typeConfigurationPackage, $self->{Name}."TypeConfiguration.cs", $self->{TypeConfigurationContent});
    SaveFile($typeConfigurationPackage, $self->{Name}.".sql", $self->{DDLSql});
}

sub setProperty{
    my ($self, $properties) = @_;

    my @notBaseProperties = grep {
        my $found = 0;
        foreach my $baseProperty (@{$self->{BaseProperties}}){
            if($_->{Name} eq $baseProperty->{Name}){
                $found = 1;
                last;
            }
        }
        !$found
    } @$properties;

    $self->{Properties} = \@notBaseProperties;
}

1;
